using NLog;
using NLog.Fluent;
using SqlSugar;
using SqlSugar.Extensions;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http.Headers;
using System.Net.Mail;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
using Yywl.Svc.Core;
using Yywl.Svc.Model.ViewModel;


namespace Yywl.Svc
{



    public partial class Service1 : ServiceBase
    {
        //定时器，根据配置文件执行
        private System.Timers.Timer autoPubshTimer;
        //即时推送
        private System.Timers.Timer rightNowPubshTimer;
        //数据库同步服务
        private System.Timers.Timer dbAsyncTimer;

        //private static SqlSugarClient dbHelper = SqlSugarDbHelper.GetConnetion();

        private bool _isPushLockFlag = false; //锁定本次推送

        //日志
        NLog.Logger _logger = LogManager.GetLogger("log");
        private Dictionary<string, int> _processRestartCounts = new Dictionary<string, int>(); // 跟踪进程重启次数


        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            _logger.Info("服务启动");

            autoPubshTimer = new System.Timers.Timer();
            //定时器
            // int minutes = 1;
            autoPubshTimer.Interval = 1000 * Convert.ToInt32(ConfigHelper.GetAppConfigToInt32("PushTime"));
            autoPubshTimer.Elapsed += new ElapsedEventHandler(autoPubshTimer_Elapsed);
            autoPubshTimer.Start();

            //即时任务
            rightNowPubshTimer = new System.Timers.Timer();
            rightNowPubshTimer.Interval = 1000;
            rightNowPubshTimer.Elapsed += new ElapsedEventHandler(autoPubshTimerRightNow_Elapsed);
            rightNowPubshTimer.Start();



        }

        /// <summary>
        /// 检测进程状态
        /// </summary>
        /// <param name="state"></param>
        public void DoTask_CheckProcessStatus(object state)
        {
            try
            {
                _logger.Debug("开始检测进程状态");

                // 从配置文件或数据库读取需要监控的进程列表
                var processesToMonitor = GetProcessesToMonitor();

                foreach (var processInfo in processesToMonitor)
                {
                    CheckAndRestartProcess(processInfo);
                }
            }
            catch (Exception ex)
            {
                _logger.Error("检测进程状态时发生错误: " + ex.Message);
            }
        }

        /// <summary>
        /// 获取需要监控的进程列表
        /// </summary>
        /// <returns>进程信息列表</returns>
        private List<ProcessInfoDto> GetProcessesToMonitor()
        {
            // 这里可以从配置文件、数据库或其他存储方式读取进程配置
            var processesList = new List<ProcessInfoDto>();

            try
            {
                // 尝试从配置文件读取进程配置
                string configFilePath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "ProcessConfig.json");
                _logger.Info($"尝试读取配置文件: {configFilePath}");
                
                if (!File.Exists(configFilePath))
                {
                    _logger.Error($"配置文件不存在: {configFilePath}");
                    return processesList;
                }
                
                string processesConfig = File.ReadAllText(configFilePath, Encoding.UTF8);
                if (!string.IsNullOrEmpty(processesConfig))
                {
                    // 尝试JSON格式解析，直接读取ProcessConfig.json文件
                    processesList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ProcessInfoDto>>(processesConfig);

                }
                else
                {
                    _logger.Warn("配置文件中未找到MonitoredProcesses项");
                }

            }
            catch (Exception ex)
            {
                _logger.Error("读取进程配置时发生错误: " + ex.Message);
                if (ex.InnerException != null)
                {
                    _logger.Error("内部错误: " + ex.InnerException.Message);
                }
            }

            return processesList;
        }

        /// <summary>
        /// 检查并重启进程
        /// </summary>
        /// <param name="processInfo">进程信息</param>
        private void CheckAndRestartProcess(ProcessInfoDto processInfo)
        {
            try
            {
                // 检查进程是否正在运行
                bool isRunning = IsProcessRunning(processInfo.ProcessName);

                if (!isRunning)
                {
                    _logger.Warn($"进程 {processInfo.ProcessName} 未运行");

                    // 记录到数据库
                    LogProcessStatus(processInfo.ProcessName, false);

                    // 发送告警通知
                    SendAlert(processInfo.ProcessName, "进程未运行");

                    // 如果配置了自动重启，则尝试重启进程
                    if (processInfo.AutoRestart && File.Exists(processInfo.ProcessPath))
                    {
                        // 检查最大重启次数限制
                        int restartCount = GetRestartCount(processInfo.ProcessName);
                        if (processInfo.MaxRestartCount > 0 && restartCount >= processInfo.MaxRestartCount)
                        {
                            _logger.Warn($"进程 {processInfo.ProcessName} 已达到最大重启次数限制 ({processInfo.MaxRestartCount})，不再尝试重启");
                            SendAlert(processInfo.ProcessName, $"进程已达到最大重启次数限制 ({processInfo.MaxRestartCount})");
                            return;
                        }

                        // 应用重启间隔
                        if (processInfo.RestartIntervalMs > 0 && restartCount > 0)
                        {
                            _logger.Info($"应用重启间隔 {processInfo.RestartIntervalMs}ms");
                            Thread.Sleep(processInfo.RestartIntervalMs);
                        }

                        _logger.Info($"尝试重启进程 {processInfo.ProcessName}（第{restartCount + 1}次）");
                        StartProcess(processInfo);

                        // 增加重启计数
                        IncrementRestartCount(processInfo.ProcessName);

                        // 检查重启是否成功
                        Thread.Sleep(2000); // 等待进程启动
                        if (IsProcessRunning(processInfo.ProcessName))
                        {
                            _logger.Info($"进程 {processInfo.ProcessName} 重启成功");
                            LogProcessStatus(processInfo.ProcessName, true, "重启成功");
                            // 重置重启计数
                            ResetRestartCount(processInfo.ProcessName);
                        }
                        else
                        {
                            _logger.Error($"进程 {processInfo.ProcessName} 重启失败");
                            LogProcessStatus(processInfo.ProcessName, false, "重启失败");
                            SendAlert(processInfo.ProcessName, "进程重启失败");
                        }
                    }
                }
                else
                {
                    _logger.Debug($"进程 {processInfo.ProcessName} 正在运行");
                    // 如果进程正在运行，重置重启计数
                    ResetRestartCount(processInfo.ProcessName);
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"检查/重启进程 {processInfo.ProcessName} 时发生错误: " + ex.Message);
            }
        }

        /// <summary>
        /// 检查进程是否正在运行
        /// </summary>
        /// <param name="processName">进程名称</param>
        /// <returns>是否运行</returns>
        private bool IsProcessRunning(string processName)
        {
            try
            {
                Process[] processes = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(processName));
                return processes.Length > 0;
            }
            catch (Exception ex)
            {
                _logger.Error($"检查进程 {processName} 状态时发生错误: " + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 启动进程
        /// </summary>
        /// <param name="processPath">进程路径</param>
        private void StartProcess(ProcessInfoDto processInfo)
        {
            try
            {
                _logger.Info($"启动进程: {processInfo.ProcessName}, 路径: {processInfo.ProcessPath}");

                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    FileName = processInfo.ProcessPath,
                    UseShellExecute = true,
                    CreateNoWindow = false
                };

                // 添加启动参数
                if (!string.IsNullOrEmpty(processInfo.StartArguments))
                {
                    startInfo.Arguments = processInfo.StartArguments;
                    _logger.Info($"使用启动参数: {processInfo.StartArguments}");
                }

                Process.Start(startInfo);
            }
            catch (Exception ex)
            {
                _logger.Error($"启动进程 {processInfo.ProcessName} 时发生错误: " + ex.Message);
                if (ex.InnerException != null)
                {
                    _logger.Error("内部错误: " + ex.InnerException.Message);
                }
                throw;
            }
        }

        /// <summary>
        /// 获取进程的重启次数
        /// </summary>
        /// <param name="processName">进程名称</param>
        /// <returns>重启次数</returns>
        private int GetRestartCount(string processName)
        {
            if (_processRestartCounts.ContainsKey(processName))
            {
                return _processRestartCounts[processName];
            }
            return 0;
        }

        /// <summary>
        /// 增加进程的重启次数
        /// </summary>
        /// <param name="processName">进程名称</param>
        private void IncrementRestartCount(string processName)
        {
            if (_processRestartCounts.ContainsKey(processName))
            {
                _processRestartCounts[processName]++;
            }
            else
            {
                _processRestartCounts[processName] = 1;
            }
        }

        /// <summary>
        /// 重置进程的重启次数
        /// </summary>
        /// <param name="processName">进程名称</param>
        private void ResetRestartCount(string processName)
        {
            if (_processRestartCounts.ContainsKey(processName))
            {
                _processRestartCounts[processName] = 0;
            }
        }

        /// <summary>
        /// 记录进程状态到数据库
        /// </summary>
        /// <param name="processName">进程名称</param>
        /// <param name="isRunning">是否运行</param>
        /// <param name="statusMessage">状态消息</param>
        private void LogProcessStatus(string processName, bool isRunning, string statusMessage = "")
        {
            try
            {
                // 这里应该实现数据库记录逻辑
                // 由于数据库连接和表结构未知，这里只记录日志
                string message = $"进程 {processName} - 状态: {(isRunning ? "运行中" : "未运行")}";
                if (!string.IsNullOrEmpty(statusMessage))
                {
                    message += $" - {statusMessage}";
                }
                _logger.Info(message);

                // 实际项目中应使用SqlSugar等ORM将数据写入数据库
                // 例如: dbHelper.Insertable(new ProcessLog { ... }).ExecuteCommand();
            }
            catch (Exception ex)
            {
                _logger.Error($"记录进程 {processName} 状态时发生错误: " + ex.Message);
            }
        }

        /// <summary>
        /// 发送告警通知
        /// </summary>
        /// <param name="processName">进程名称</param>
        /// <param name="message">告警消息</param>
        private void SendAlert(string processName, string message)
        {
            try
            {
                string alertMessage = $"进程监控告警 - 进程: {processName}, 消息: {message}, 时间: {DateTime.Now}";
                _logger.Warn(alertMessage);

                // 发送邮件告警
                if (ConfigHelper.GetAppConfig("EnableEmailAlert") == "true")
                {
                    SendEmailAlert(alertMessage);
                }

                // 发送短信告警
                if (ConfigHelper.GetAppConfig("EnableSmsAlert") == "true")
                {
                    SendSmsAlert(alertMessage);
                }

                // 发送钉钉告警
                if (ConfigHelper.GetAppConfig("EnableDingTalkAlert") == "true")
                {
                    //默认手机号
                    var  defaultPhonesList = ConfigHelper.GetAppConfig("DingTalkDefaultPhone").Split(',').ToList();
                    SendDingTalkAlert(alertMessage, defaultPhonesList, checkBox_Phones: true);

                }
            }
            catch (Exception ex)
            {
                _logger.Error($"发送告警时发生错误: " + ex.Message);
            }
        }

        /// <summary>
        /// 发送邮件告警
        /// </summary>
        /// <param name="message">告警消息</param>
        private void SendEmailAlert(string message)
        {
            try
            {
                _logger.Info($"准备发送邮件告警: {message}");

                // 从配置文件读取邮件服务器信息
                string smtpServer = ConfigHelper.GetAppConfig("SmtpServer");
                int smtpPort = 25; // 默认端口
                try
                {
                    smtpPort = ConfigHelper.GetIntValue("SmtpPort");
                }
                catch
                {
                    _logger.Warn("未找到SmtpPort配置或配置无效，使用默认端口25");
                }

                string smtpUser = ConfigHelper.GetAppConfig("SmtpUser");
                string smtpPassword = ConfigHelper.GetAppConfig("SmtpPassword");
                string fromEmail = ConfigHelper.GetAppConfig("FromEmail");
                string toEmail = ConfigHelper.GetAppConfig("ToEmail");

                // 验证必要的配置是否存在
                if (string.IsNullOrEmpty(smtpServer) || string.IsNullOrEmpty(fromEmail) || string.IsNullOrEmpty(toEmail))
                {
                    _logger.Error("邮件发送失败: 缺少必要的邮件服务器配置");
                    return;
                }

                // 创建邮件消息
                MailMessage mailMessage = new MailMessage
                {
                    From = new MailAddress(fromEmail),
                    Subject = "WinSupervisor进程监控告警",
                    Body = message,
                    IsBodyHtml = false
                };

                // 添加收件人
                foreach (string email in toEmail.Split(new[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    mailMessage.To.Add(new MailAddress(email.Trim()));
                }

                // 创建SMTP客户端
                using (SmtpClient smtpClient = new SmtpClient(smtpServer, smtpPort))
                {
                    // 设置凭据
                    if (!string.IsNullOrEmpty(smtpUser) && !string.IsNullOrEmpty(smtpPassword))
                    {
                        smtpClient.Credentials = new NetworkCredential(smtpUser, smtpPassword);
                    }

                    // 设置SSL（可选，根据邮件服务器要求）
                    smtpClient.EnableSsl = ConfigHelper.GetAppConfig("SmtpEnableSsl") == "true";

                    // 设置超时时间
                    smtpClient.Timeout = 30000; // 30秒

                    // 发送邮件
                    _logger.Info($"正在发送邮件到 {toEmail}");
                    smtpClient.Send(mailMessage);
                    _logger.Info("邮件发送成功");
                }
            }
            catch (Exception ex)
            {
                _logger.Error("发送邮件告警时发生错误: " + ex.Message);
                if (ex.InnerException != null)
                {
                    _logger.Error("内部错误: " + ex.InnerException.Message);
                }
            }
        }

        /// <summary>
        /// 发送短信告警
        /// </summary>
        /// <param name="message">告警消息</param>
        private void SendSmsAlert(string message)
        {
            try
            {
                // 这里实现短信发送逻辑
                // 由于短信API配置未知，这里只记录日志
                _logger.Info($"短信告警已触发: {message}");

                // 实际实现应调用短信API发送短信
            }
            catch (Exception ex)
            {
                _logger.Error("发送短信告警时发生错误: " + ex.Message);
            }
        }

        /// <summary>
        /// 发送钉钉告警
        /// </summary>
        /// <param name="message">告警消息</param>
        private async void SendDingTalkAlert(string message, List<string> phoneList, bool checkBox_Phones = false)
        {
            try
            {
                // 这里实现钉钉告警发送逻辑
                // 由于钉钉机器人配置未知，这里只记录日志
                _logger.Info($"钉钉告警已触发: {message}");
                string webhookUrl = ConfigHelper.GetAppConfig("DingTalkWebhook");
                var robot = new DingTalkRobot(webhookUrl);
                // 实际实现应调用钉钉机器人API发送消息
                {
                    //@的人员手机号列表

                    // 1、发送文本消息
                    _logger.Info("发送文本消息...");


                    if (checkBox_Phones)
                    {
                        //发送指定人员
                        var textResult = await robot.SendTextMessage(
                  message,
                    phoneList,  // 需要@的手机号
                     false  // 不@所有人
                    );

                       _logger.Info($"文本消息发送结果: {(textResult.IsSuccess ? "成功" : $"失败: {textResult.Errmsg}")}");

                    }
                    else
                    {
                        //所有人
                        var textResult = await robot.SendTextMessage(
           message,
            new List<string> { },  // 手机号列表为空即可
             true  // true表示@所有人
            );

                        _logger.Info($"文本消息发送结果: {(textResult.IsSuccess ? "成功" : $"失败: {textResult.Errmsg}")}");
                    }


                    //                // 2、发送链接消息
                    //                Console.WriteLine("\n发送链接消息...");
                    //                var linkResult = await robot.SendLinkMessage(
                    //                    "【mes机器人】钉钉开放平台",
                    //                    "钉钉开放平台提供了丰富的API接口，方便开发者扩展钉钉的功能",
                    //                    "https://open.dingtalk.com/",
                    //                    "https://gw.alicdn.com/tfs/TB1H0W7k6D1gK0jSZFsXXaNlXXa-200-200.png"
                    //                );
                    //                MessageBox.Show($"链接消息发送结果: {(linkResult.IsSuccess ? "成功" : $"失败: {linkResult.Errmsg}")}");

                    //                // 3、发送Markdown消息
                    //                Console.WriteLine("\n发送Markdown消息...");
                    //                string markdownText = @"
                    //# 【mes机器人】这是一个Markdown标题
                    //## 这是二级标题
                    //- 列表项1
                    //- 列表项2
                    //**加粗文本**
                    //[链接文本](https://open.dingtalk.com/)
                    //";
                    //                var markdownResult = await robot.SendMarkdownMessage(
                    //                    "Markdown消息测试",
                    //                    markdownText,
                    //                    null,
                    //                    false
                    //                );
                    //                MessageBox.Show($"Markdown消息发送结果: {(markdownResult.IsSuccess ? "成功" : $"失败: {markdownResult.Errmsg}")}");
                }
            }

            catch (Exception ex)
            {
                _logger.Error("发送钉钉告警时发生错误: " + ex.Message);
            }
        }



        /// <summary>
     


        protected override void OnStop()
        {
            autoPubshTimer.Stop();
            EventLog.WriteEntry("中间库服务推送停止");
        }


        #region 即时推送任务
        /// <summary>
        /// 即时推送任务
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void autoPubshTimerRightNow_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            //var date = DateTime.Now;
            //开始模型训练任务
            //ThreadPool.QueueUserWorkItem(DoTask_StartModelTrain);
            ////结束模型训练任务
            //ThreadPool.QueueUserWorkItem(DoTask_StopModelTrain);

        }
        #endregion

        #region 线程池执行任务
        void autoPubshTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            //var date = DateTime.Now;

            if (!_isPushLockFlag)
            {

                _logger.Info("-----开始执行任务---------------------");

                //定时监测进程状态
                ThreadPool.QueueUserWorkItem(DoTask_CheckProcessStatus);


                _logger.Info("-----执行任务完成---------------------");

                _isPushLockFlag = true;

            }
            _isPushLockFlag = false;//重置

        }
        #endregion


    }


}
